﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using S7.Net;
using System.Dynamic;
using System.Collections;

namespace S7PlcHelper
{
    public class PlcHelper : Plc
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="cpu"></param>
        /// <param name="ip"></param>
        /// <param name="rack"></param>
        /// <param name="slot"></param>
        public PlcHelper(CpuType cpu, string ip, short rack, short slot) : base(cpu, ip, rack, slot)
        {


        }


        public PlcHelper(PlcConfig mPlcConfig) : base(mPlcConfig.cputype, mPlcConfig.ip, mPlcConfig.rack, mPlcConfig.slot)
        { 
        }



        /// <summary>
        /// 返回error表示异常
        /// </summary>
        /// <param name="txt_read_addr"></param>
        /// <returns></returns>
        public object readPlc(string txt_read_addr)
        {
            object returndata;

            if (IsConnected == false)
            {
                return "未连接PLC";
            }

            try
            {
                string[] arr = (txt_read_addr.ToUpper()).Split('.');//将txt_read_addr文本框中的数据转为大写字母，并用“.”拆分后存放到arr数组中
                string valuetype = arr[1].Substring(0, 3);//取数组中的第二个元素的前三位，用以确认读取的PLC数据类型
                                                          //西门子PLC数据类型：DBX(位，bool）DBB(字节,byte）DBW(字,word）DBD(双字,dword） 


                if (valuetype == "DBX")
                {
                    returndata = (bool)Read(txt_read_addr.ToUpper());
                }

                else if (valuetype == "DBW")
                {
                    returndata = ((ushort)Read(txt_read_addr.ToUpper())).ConvertToShort();
                }

                else if (valuetype == "DBD")
                {
                    returndata = ((uint)Read(txt_read_addr.ToUpper())).ConvertToFloat();

                }

                else
                {
                    returndata = "格式有误";

                }




            }
            catch (Exception Ex)
            {
                returndata = Ex.Message;
            }

            return returndata;

        }
        /// <summary>
        /// 写入db块
        /// </summary>
        /// <param name="txt_write_addr"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public object writePlc(string txt_write_addr, string value)
        {
            object returndata = true;

            if (IsConnected == false)
            {
                return "未连接PLC";
            }

            try
            {
                string[] arr = (txt_write_addr.ToUpper()).Split('.');//将txt_read_addr文本框中的数据转为大写字母，并用“.”拆分后存放到arr数组中
                string valuetype = arr[1].Substring(0, 3);//取数组中的第二个元素的前三位，用以确认读取的PLC数据类型
                                                          //西门子PLC数据类型：DBX(位，bool）DBB(字节,byte）DBW(字,word）DBD(双字,dword） 


                if (valuetype == "DBX")
                {
                    Write(txt_write_addr.ToUpper(), Convert.ToBoolean(value));
                }

                else if (valuetype == "DBW")
                {
                    var _value = short.Parse(value);
                    Write(txt_write_addr.ToUpper(), _value);
                }

                else if (valuetype == "DBD")
                {
                    double _value = double.Parse(value);
                    Write(txt_write_addr.ToUpper(), _value);
                }

                else
                {
                    returndata = "格式有误";

                }




            }
            catch (Exception Ex)
            {
                returndata = Ex.Message;
            }

            return returndata;

        }

        /// <summary>
        /// 采集相同
        /// </summary>
        /// <param name="mPlcConfig"></param>
        /// <param name="db"></param>
        /// <param name="datatype"></param>
        /// <param name="startadr"></param>
        /// <returns></returns>
        public object readbystarttype(int db, string datatype, decimal startadr)
        {
            int int_now = (int)Math.Floor(startadr); //取出整数位 
            int double_now = (int)(startadr % 1 * 10); //小数位
            int varcount = 1;
            try
            {
                object v_return = null;
                if (datatype=="BOOL")
                {
                    byte[] bytes = ReadBytes(DataType.DataBlock, db, int_now, varcount);
                  //  byte[] bytes =  (byte[]) Read(DataType.DataBlock, db, int_now, (VarType)Enum.Parse(typeof(VarType), "Byte"), varcount);

                      v_return = bytes[0].SelectBit(double_now); 

                }
                else
                {
                      v_return = Read(DataType.DataBlock, db, int_now, (VarType)Enum.Parse(typeof(VarType), datatype), varcount);

                }
                

                return v_return;
            }
            catch (Exception x)
            {
                return null; 
            }

               
           
        }


        /// <summary>
        /// 将db块所有bytes数据根据PlcTags 来转换
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="PlcTags"></param>
        /// <returns></returns>
        public object bytes2obj(byte[] bytes, List<PlcTag> PlcTags)
        {
             
            decimal now_i = 0;
            dynamic returnobject = new ExpandoObject();
            var dic = (IDictionary<string, object>)returnobject;

            for (int i = 0; i < PlcTags.Count; i++)
            {

                int int_Ceiling = (int)Math.Ceiling(now_i); //向上取出整数位 

                switch (PlcTags[i].type.ToUpper())
                {
                    case "BOOL":
                        int int_now = (int)Math.Floor(now_i); //取出整数位 
                        int double_now = (int)(now_i % 1 * 10); //小数位
                        bool boolVar = bytes[int_now].SelectBit(double_now);
                       // PlcTags[i].Value = boolVar; 
                        dic[PlcTags[i].title] = boolVar;
                        if (double_now < 7)
                        {
                            now_i = now_i + (decimal)0.1;
                        }
                        else
                        {
                            now_i = int_now + 1;
                        }

                        break;
                    case "REAL":
                        if (Convert.ToBoolean(int_Ceiling % 2))
                        {
                            now_i = int_Ceiling + 1;
                        }
                        Double realVariable = S7.Net.Types.Double.FromByteArray(bytes.Skip((int)now_i).Take(4).ToArray());
                        //PlcTags[i].Value = realVariable;
                        dic[PlcTags[i].title] = realVariable;
                        now_i = now_i + 4;
                        break;

                    case "INT":
                        if (Convert.ToBoolean(int_Ceiling % 2))
                        {
                            now_i = int_Ceiling + 1;
                        }
                        int intVariable = S7.Net.Types.Int.FromByteArray(bytes.Skip((int)now_i).Take(2).ToArray());
                        // PlcTags[i].Value = intVariable;
                        dic[PlcTags[i].title] = intVariable;
                        now_i = now_i + 2;
                        break;

                    case "DWord":
                        if (Convert.ToBoolean(int_Ceiling % 2))
                        {
                            now_i = int_Ceiling + 1;
                        }
                        uint dWordVariable = S7.Net.Types.DWord.FromByteArray(bytes.Skip((int)now_i).Take(4).ToArray());
                       // PlcTags[i].Value = dWordVariable;
                        dic[PlcTags[i].title] = dWordVariable;
                        now_i = now_i + 4;
                        break;
                    case "Word":
                        if (Convert.ToBoolean(int_Ceiling % 2))
                        {
                            now_i = int_Ceiling + 1;
                        }
                        var wordVariable = S7.Net.Types.Word.FromByteArray(bytes.Skip((int)now_i).Take(2).ToArray());
                       // PlcTags[i].Value = wordVariable; 
                        dic[PlcTags[i].title] = wordVariable;
                        now_i = now_i + 2;
                        break;

                    default:

                        break;
                }


            }

            return returnobject;
        }





    }
}
